{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "initial_id",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-04T15:08:58.021266Z",
     "start_time": "2025-09-04T15:08:57.435663Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import osmium as osm\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "31b28856e42ca0fd",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-04T05:24:50.462810Z",
     "start_time": "2025-09-04T05:24:50.447179Z"
    }
   },
   "outputs": [],
   "source": [
    "class OSMHandler(osm.SimpleHandler):\n",
    "    def __init__(self):\n",
    "        super(OSMHandler, self).__init__()\n",
    "        self.poi_data = []  # 用于存储提取的POI数据\n",
    "\n",
    "    def process_poi(self, elem, elem_type):\n",
    "        \"\"\"处理元素并提取POI信息\"\"\"\n",
    "        # 检查元素是否有标签（tags），没有标签的通常不是POI\n",
    "        if len(elem.tags) == 0:\n",
    "            return\n",
    "        \n",
    "        # 节点可直接读取经纬度；way/relation 无单一经纬度，这里记为空\n",
    "        lon = getattr(elem, 'location', None).lon if (elem_type == 'node' and getattr(elem, 'location', None) and getattr(elem.location, 'valid', False)) else None\n",
    "        lat = getattr(elem, 'location', None).lat if (elem_type == 'node' and getattr(elem, 'location', None) and getattr(elem.location, 'valid', False)) else None\n",
    "\n",
    "        # 提取元素的基本信息和标签\n",
    "        for tag in elem.tags:\n",
    "            self.poi_data.append([\n",
    "                elem_type,        # 元素类型（node, way, relation）\n",
    "                elem.id,          # 元素ID\n",
    "                elem.version,     # 版本号\n",
    "                elem.visible,     # 是否可见\n",
    "                pd.Timestamp(elem.timestamp),  # 时间戳，转换为pandas的Timestamp格式\n",
    "                elem.uid,         # 用户ID\n",
    "                elem.user,        # 用户名\n",
    "                elem.changeset,   # 变更集ID\n",
    "                lon,              # 经度（node 有值，way/relation 为 None）\n",
    "                lat,              # 纬度（node 有值，way/relation 为 None）\n",
    "                tag.k,            # 标签键（如：amenity, name）\n",
    "                tag.v             # 标签值（如：restaurant, Starbucks）\n",
    "            ])\n",
    "\n",
    "    def node(self, n):\n",
    "        \"\"\"处理节点\"\"\"\n",
    "        self.process_poi(n, \"node\")\n",
    "\n",
    "    def way(self, w):\n",
    "        \"\"\"处理路径\"\"\"\n",
    "        self.process_poi(w, \"way\")\n",
    "\n",
    "    def relation(self, r):\n",
    "        \"\"\"处理关系\"\"\"\n",
    "        self.process_poi(r, \"relation\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "be6aa4e29d53e053",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-04T05:27:16.818444Z",
     "start_time": "2025-09-04T05:26:03.185644Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   type        id  version  visible                 timestamp       uid  \\\n",
      "0  node  31236584        6     True 2020-06-27 06:04:04+00:00  10598740   \n",
      "1  node  31236584        6     True 2020-06-27 06:04:04+00:00  10598740   \n",
      "2  node  31236584        6     True 2020-06-27 06:04:04+00:00  10598740   \n",
      "3  node  31236737        5     True 2019-05-18 13:33:27+00:00   3150532   \n",
      "4  node  31236738        5     True 2019-05-18 13:33:27+00:00   3150532   \n",
      "\n",
      "       user  changeset         lon        lat  tag_key          tag_value  \n",
      "0  yossaito   87218546  139.768683  35.634935  highway  motorway_junction  \n",
      "1  yossaito   87218546  139.768683  35.634935     name                 台場  \n",
      "2  yossaito   87218546  139.768683  35.634935      ref               1101  \n",
      "3       dqn   70387330  139.756849  35.640549  highway    traffic_signals  \n",
      "4       dqn   70387330  139.757701  35.640550  highway    traffic_signals  \n"
     ]
    }
   ],
   "source": [
    "osm_handler = OSMHandler()\n",
    "osm_handler.apply_file(r\"D:\\Repository\\city-data-reshape\\datas\\tokyo.osm\")\n",
    "\n",
    "# 增加 lon/lat 两列\n",
    "df_poi = pd.DataFrame(\n",
    "    osm_handler.poi_data,\n",
    "    columns=[\n",
    "        'type', 'id', 'version', 'visible', 'timestamp',\n",
    "        'uid', 'user', 'changeset', 'lon', 'lat', 'tag_key', 'tag_value'\n",
    "    ]\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "01441e03",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_poi = df_poi.dropna(subset=['lon', 'lat'])  # 删除 lon 或 lat 为空的行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "563962adaff1466b",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-04T05:29:59.758473Z",
     "start_time": "2025-09-04T05:29:43.935709Z"
    }
   },
   "outputs": [],
   "source": [
    "df_poi.to_csv('tokyo_pois_jinweidu.csv', index=False, encoding='utf-8')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac2a157eb9ceed98",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3.10.6-learn",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
